package com.wyw.function.learning.demo5;

import com.wyw.function.learning.common.Dish;
import com.wyw.function.learning.common.DishClient;

import java.util.Collections;
import java.util.List;
import java.util.OptionalInt;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * @Title   使用流
 * @Description 数值流
 * @Author Mr Wu yewen.wu.china@gmail.com
 * Update History:
 * Author        Time            Content
 */
public class DemoClient11 {

//    public static void main(String[] args) {
//        List<Dish> menu = DishClient.getMenu();
//        // 像这样会有一个装箱的成本，每个Integer必须拆箱成为原始类型，在求和，所以Java8引入了三个原始类型流特化接口来解决这个问题： IntStream, DoubleStream, LongStream
//        // 映射到数流值： 将流转化为特化版本的常用方法，mapToInt、mapToDouble、mapToLong， 如果流为空，sum默认0，IntStream还支持max、min、average等方便方法
//        Integer reduce = menu.stream().map(Dish::getCalories).reduce(0, Integer::sum);
//        int reduce1 = menu.stream().mapToInt(Dish::getCalories).reduce(0, Integer::sum);
//
//        System.out.println(reduce);
//        System.out.println(reduce1);
//    }

    // 转换回对象流    数值流转化为非特化流
//    public static void main(String[] args) {
//        List<Dish> menu = DishClient.getMenu();
//        IntStream intStream = menu.stream().mapToInt(Dish::getCalories);
//        Stream<Integer> boxed = intStream.boxed();
//    }

    // 默认值OptionalInt    Optional类：表示值存在或不存在的容器    Optional可以用Integer、String等参考类型来参数化
    // 如果需要计算IntStream中的最大元素，就得换方案了，因为0是错误结果，需要区分没有元素的流和最大值真的是0的流
//    public static void main(String[] args) {
//        List<Dish> menu = DishClient.getEmptyMenu();
//        OptionalInt max = menu.stream().mapToInt(Dish::getCalories).max();
//        int maxNum = max.orElse(1);
//        System.out.println(maxNum);
//    }

    // 数值范围：Java 8 引入了两个可以用于IntStream和LongStream的静态方法，帮助生成这种范围的：range和rangeClosed。
    // 这两个方法都是第一个参数接收起始值，第二个参数接收结束值。但range是不包括结束值的，而rangeClosed则包含结束值
//    public static void main(String[] args) {
////        IntStream intStream = IntStream.range(1, 100).filter(n -> n % 2 == 0);
//        IntStream intStream = IntStream.rangeClosed(1, 100).filter(n -> n % 2 == 0);
//        System.out.println(intStream.count());
//    }

    // 数值流应用，勾股数，创建一个勾股数流
    // 表示三元数：使用具体由三个元素的int数组，比如new int[]{3,4,5},来表示勾股数(3,4,5)
    // 筛选成立的组合：假定有人为你提供了三元数中前两个数字，a和b。怎么判断它是否能购成一组勾股数呢？需要测试a方+b方的平方根是不是整数
    public static void main(String[] args) {
        Stream<int[]> stream = IntStream.rangeClosed(1, 100).boxed()
                .flatMap(a -> IntStream.rangeClosed(a, 100).filter(b -> Math.sqrt(a * a + b * b) % 1 == 0)
                        .mapToObj(b -> new int[]{a, b, (int) Math.sqrt(a * a + b * b)})
                );

        Stream<int[]> stream1 = IntStream.rangeClosed(1, 100).boxed()
                .flatMap(a -> IntStream.rangeClosed(a, 100)
                        .mapToObj(b -> new int[]{a, b, (int) Math.sqrt(a * a + b * b)})// mapToObj可以将IntStream返回对象流
                        .filter(t->t[2] %1 == 0)
                );

        List<int[]> collect = stream.collect(Collectors.toList());
        List<int[]> collect1 = stream1.collect(Collectors.toList());


    }


}
